﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PageHandler.cs" company="Anton Frattaroli">
//   Copyright (c) Anton Frattaroli. All rights reserved.
// </copyright>
// <summary>
//   Defines the PageHandler class that inherits the Page class and handles all virtual page requests.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Lidocaine
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;

    /// <summary>
    /// Defines the PageHandler class.
    /// </summary>
    public class PageHandler : Page, IRequiresSessionState
    {
        #region Fields
        /// <summary>
        /// Stores the header PlaceHolder control.
        /// </summary>
        private PlaceHolder header;

        /// <summary>
        /// Stores the main column PlaceHolder control.
        /// </summary>
        private PlaceHolder main;

        /// <summary>
        /// Stores the right column PlaceHolder control.
        /// </summary>
        private PlaceHolder right;

        /// <summary>
        /// Stores the footer PlaceHolder control.
        /// </summary>
        private PlaceHolder footer;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the Placeholder control that serves as the page's header control collection.
        /// </summary>
        public PlaceHolder TemplateHeader
        {
            get
            {
                if (this.header == null)
                {
                    this.header = new PlaceHolder();
                }

                return this.header;
            }

            set
            {
                this.header = value;
            }
        }

        /// <summary>
        /// Gets or sets the Placeholder control that serves as the page's main column control collection.
        /// </summary>
        public PlaceHolder Main
        {
            get
            {
                if (this.main == null)
                {
                    this.main = new PlaceHolder();
                }

                return this.main;
            }

            set
            {
                this.main = value;
            }
        }

        /// <summary>
        /// Gets or sets the Placeholder control that serves as the page's right column control collection.
        /// </summary>
        public PlaceHolder Right
        {
            get
            {
                if (this.right == null)
                {
                    this.right = new PlaceHolder();
                }

                return this.right;
            }

            set
            {
                this.right = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the Placeholder control that serves as the page's footer control collection.
        /// </summary>
        public PlaceHolder Footer
        {
            get
            {
                if (this.footer == null)
                {
                    this.footer = new PlaceHolder();
                }

                return this.footer;
            }

            set
            {
                this.footer = value;
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// The page initialization method.
        /// </summary>
        /// <param name="sender">The HttpApplication object that requested this method.</param>
        /// <param name="e">The page's event arguments.</param>
        protected void Page_Init(object sender, EventArgs e)
        {
            // set up doctype, html, head, body elements, add form element.
            Literal html = new Literal();
            html.EnableViewState = false;
            html.Text = "<!DOCTYPE html><html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">";
            this.Controls.Add(html);
            html = new Literal();
            html.EnableViewState = false;
            html.Text = "<meta name=\"keywords\" content=\"weight gain, multiple births, pregnancy diet, prenatal nturition, maternal nutrition, twins, triplets, quadruplets, pregnancy, diet, and multiples\" /><meta name=\"description\" content=\"drbarbaraluke.com focuses on nutrition, weight gain, multiple births, pregnancy diet and pregnancy, including the Top 25 Food All-Stars, optimal bone health, preventing premature birth, and improving outcomes in multiple pregnancy. Personalized programs are available, based on the award-winning book, When You're Expecting Twins, Triplets, or Quads (HarperCollins, 1999)\" />";
            HtmlHead head = new HtmlHead();
            head.Controls.Add(html);
            this.Controls.Add(head);
            html = new Literal();
            html.Text = "<body>";
            this.Controls.Add(html);
            this.Controls.Add(new HtmlForm());
            html = new Literal();
            html.Text = "</div></div></body></html>";
            this.Controls.Add(html);
        }

        /// <summary>
        /// The page load method.
        /// </summary>
        /// <param name="sender">The HttpApplication object that requested this method.</param>
        /// <param name="e">The page's event arguments.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.ContentEncoding = Encoding.UTF8;
            Response.ContentType = "text/html";
            this.MaintainScrollPositionOnPostBack = true;
            this.Form.Action = Request.RawUrl;
            this.TemplateHeader.Controls.Clear();
            this.Main.Controls.Clear();
            this.Right.Controls.Clear();
            this.Footer.Controls.Clear();
            PageLayout p = new PageLayout(Request.Path.TrimStart("/".ToCharArray()));
            this.Title = p.Title + " - " + Environmental.Title;
            Literal html = new Literal();
            html.EnableViewState = false;
            if (p.Css != null)
            {
                html.Text += string.Format(CultureInfo.InvariantCulture, "<link rel=\"stylesheet\" type=\"text/css\" href=\"/lidocaine.ashx?f=LoadCSS&ID={0}\" />", p.Css.ScriptId);
            }

            if (p.JS != null)
            {
                html.Text += string.Format(CultureInfo.InvariantCulture, "<script type=\"text/javascript\" src=\"/lidocaine.ashx?f=LoadJS&ID={0}\"></script>", p.JS.ScriptId);
            }

            this.TemplateHeader.Controls.Add(html);
            
            html = new Literal();
            html.Text = "<meta name=\"viewport\" content=\"width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;\" />";
            this.header.Controls.Add(html);

            html = new Literal();
            html.Text = "<div id=\"divContainer\"><div id=\"divHeader\"><h1 style=\"display:none;\">" + p.Title + "</h1><a style=\"display: none;\" href=\"#Lidocaine__Content\">Click Here To Jump To The Content</a>";
            this.Form.Controls.Add(html);
            if (p.Header != null)
            {
                this.TemplateHeader = this.ParseContent(p.Header.TemplateText, this.TemplateHeader);
                this.Form.Controls.Add(this.TemplateHeader);
            }

            StringBuilder topNav = new StringBuilder();
            IList<NavigationGroup> topNavs = p.GetNavigationGroups(NavigationGroupArea.Top);
            for (int i = 0; i < topNavs.Count; i++)
            {
                topNav.AppendFormat("<div class=\"TopNavWrapper\"><ul class=\"TopNav TopNav{0}\">", i + 1);
                for (int j = 0; j < topNavs[i].Items.Count; j++)
                {
                    if (!string.IsNullOrEmpty(topNavs[i].Items[j].Link))
                    {
                        topNav.AppendFormat("<li><a href=\"{0}\" class=\"TopNavItem TopNav{1}Item\">{2}</a></li>", topNavs[i].Items[j].Link, i + 1, topNavs[i].Items[j].Text);
                    }
                    else
                    {
                        topNav.AppendFormat("<li><span class=\"TopNavItem TopNav{0}Item\">{1}</span></li>", i + 1, topNavs[i].Items[j].Text);
                    }
                }

                topNav.Append("</ul></div>");
            }

            html = new Literal();
            html.Text = "</div><div id=\"divTop\">" + topNav.ToString() + "</div><div id=\"divContentContainer\"><div id=\"divContent\"><a id=\"Lidocaine__Content\"></a>";
            this.Form.Controls.Add(html);

            for (int i = 0; i < p.MainModules.Count; i++)
            {
                if (p.MainModules[i].ModuleName != "Content")
                {
                    Control c = LoadControl("/modules/" + p.MainModules[i].ModulePath);
                    this.Main.Controls.Add(c);
                }
                else if (p.Content != null)
                {
                    this.Main = this.ParseContent(p.Content.Html, this.Main);
                }
            }

            this.Form.Controls.Add(this.Main);

            StringBuilder leftNav = new StringBuilder();
            IList<NavigationGroup> leftNavs = p.GetNavigationGroups(NavigationGroupArea.Left);
            for (int i = 0; i < leftNavs.Count; i++)
            {
                leftNav.AppendFormat("<div class=\"LeftNavWrapper\"><ul class=\"LeftNav LeftNav{0}\">", i + 1);
                for (int j = 0; j < leftNavs[i].Items.Count; j++)
                {
                    if (!string.IsNullOrEmpty(leftNavs[i].Items[j].Link))
                    {
                        leftNav.AppendFormat("<li><a href=\"{0}\" class=\"LeftNavItem LeftNav{1}Item\">{2}</a></li>", leftNavs[i].Items[j].Link, i + 1, leftNavs[i].Items[j].Text);
                    }
                    else
                    {
                        leftNav.AppendFormat("<li><span class=\"LeftNavItem LeftNav{0}Item\">{1}</span></li>", i + 1, leftNavs[i].Items[j].Text);
                    }
                }

                leftNav.Append("</ul></div>");
            }

            html = new Literal();
            html.Text = "</div></div><div id=\"divLeft\">" + leftNav.ToString() + "</div><div id=\"divRight\">";
            this.Form.Controls.Add(html);
            for (int i = 0; i < p.RightModules.Count; i++)
            {
                Control c = LoadControl("/modules/" + p.RightModules[i].ModulePath);
                this.Right.Controls.Add(c);
            }

            this.Form.Controls.Add(this.Right);
            html = new Literal();
            html.Text = "</div><div id=\"divFooter\">";
            this.Form.Controls.Add(html);
            if (p.Footer != null)
            {
                this.Footer = this.ParseContent(p.Footer.TemplateText, this.Footer);
                this.Form.Controls.Add(this.Footer);
            }
        }

        /// <summary>
        /// Parses scripts in order to manifest modules in content.
        /// </summary>
        /// <param name="content">The script to parse.</param>
        /// <param name="ph">The placeholder intended to place the generated controls into.</param>
        /// <returns>The placeholder fully loaded with controls parsed from the script.</returns>
        private PlaceHolder ParseContent(string content, PlaceHolder ph)
        {
            List<string> contents = new List<string>();
            List<string> moduleIDs = new List<string>();
            UserControlAsset m;
            Regex r = new Regex("<div class=\"moduleplaceholder (\\d+)[^>]+(>)", RegexOptions.Singleline);
            MatchCollection mc = r.Matches(content);
            if (mc.Count > 0)
            {
                for (int i = 0; i < mc.Count; i++)
                {
                    contents.Add(content.Substring(0, mc[i].Groups[2].Index + 1));
                    content = content.Substring(mc[i].Groups[2].Index + 1);
                    moduleIDs.Add(mc[i].Groups[1].Value);
                }

                contents.Add(content);
                Literal ltlContent = new Literal();
                ltlContent.Text = contents[0];
                ph.Controls.Add(ltlContent);
                Control c;
                for (int i = 0; i < moduleIDs.Count; i++)
                {
                    m = new UserControlAsset(Convert.ToInt32(moduleIDs[i], CultureInfo.InvariantCulture));
                    c = this.LoadControl("/modules/" + m.ModulePath);
                    ph.Controls.Add(c);
                    ltlContent = new Literal();
                    ltlContent.Text = contents[i + 1];
                    ph.Controls.Add(ltlContent);
                }
            }
            else
            {
                Literal ltlContent = new Literal();
                ltlContent.Text = content;
                ph.Controls.Add(ltlContent);
            }

            return ph;
        }
        #endregion
    }
}